#include <string.h>
#include <iostream>

using std::cout;
using std::endl;

class String
{
public:
    String()
    : _pstr(nullptr)
    /* : _pstr(new char[1]()) */
    {
        cout << "String()" << endl;
    }

    String(const char *pstr)
    : _pstr(new char[strlen(pstr) + 1]())
    {
        cout <<"String(const char *)" << endl;
        strcpy(_pstr, pstr);
    }

    //将拷贝构造函数与赋值运算符函数称为具有拷贝控制语义的函数
    //移动构造函数与移动赋值函数称为具有移动语义的函数
    //
    //具有移动语义的函数优先于具有拷贝控制语义的函数的执行
    //
    //具备拷贝语义的函数编译器会自动生成；但是具备移动语义的
    //函数编译器不会自动生成
    //
    //拷贝构造函数
    String(const String &rhs)
    : _pstr(new char[strlen(rhs._pstr) + 1]())
    {
        cout <<"String(const string &)"<< endl;
        strcpy(_pstr, rhs._pstr);
    }

    //赋值运算符函数
    String &operator=(const String &rhs)
    {
        cout << "String &operator=(const String &)" << endl;
        if(this != &rhs)//1、自复制
        /* if(*this != rhs) */
        {
            //2、释放左操作数
            delete [] _pstr;
            _pstr = nullptr;

            //3、深拷贝
            _pstr = new char[strlen(rhs._pstr) + 1]();
            strcpy(_pstr, rhs._pstr);
        }

        //4、返回*this
        return *this;
    }

    //移动构造函数
    String(String &&rhs)
    : _pstr(rhs._pstr)
    {
        cout <<"String(string &&)"<< endl;
        rhs._pstr = nullptr;
    }

    //移动赋值函数
    String &operator=(String &&rhs)
    {
        cout << "String &operator=(String &&)" << endl;
        if(this != &rhs)//1、自移动
        {
            //2、释放左操作数
            delete [] _pstr;
            _pstr = nullptr;

            //3、浅拷贝
            _pstr = rhs._pstr;
            rhs._pstr = nullptr;
        }
        //4、返回*this
        return *this;
    }

    ~String()
    {
        cout <<"~String()" << endl;
        if(_pstr)
        {
            delete [] _pstr;
            _pstr = nullptr;
        }
    }

    friend std::ostream &operator<<(std::ostream &os, const String &rhs);
private:
    char *_pstr;
};

std::ostream &operator<<(std::ostream &os, const String &rhs)
{
    if(rhs._pstr)
    {
        os << rhs._pstr;
    }

    return os;
}

void test()
{
    String s1("hello");
    cout << "s1 = " << s1 << endl;

    cout << endl;
    String s2 = s1;
    cout << "s1 = " << s1 << endl;
    cout << "s2 = " << s2 << endl;

    cout << endl;
    String s3("world");
    cout << "s3 = " << s3 << endl;

    cout << endl;
    s3 = s1;
    cout << "s1 = " << s1 << endl;
    cout << "s3 = " << s3 << endl;
}

void test2()
{
    String s1("hello");
    cout << "s1 = " << s1 << endl;

    cout << endl;
    String s2 = "world";//隐式转换,"world" ==>String("world")
    cout << "s2 = " << s2 << endl;
    /* &"world";//ok */

    cout << endl;
    String s3 = s1;
    cout << "s1 = " << s1 << endl;
    cout << "s3 = " << s3 << endl;

    cout << endl;
    s3 = String("wangdao");//临时对象的生命周期只在本行,离开本行就会销毁
    cout << "s3 = " << s3 << endl;

    cout << endl;
    String("hello") = String("hello");

    cout << endl << "std::move函数" << endl;
    String s4("wuhan");
    cout << "s4 = " << s4 << endl;

    cout << endl;
    //std::move可以将左值转换为右值,底层做的其实就是一个强制
    //转换static_cast<T &&>(lvalue)
    s4 = std::move(s4);
    cout << "s4 = " << s4 << endl;

    cout << endl;
    s4 = std::move(s1);
    cout << "s1 = " << s1 << endl;

    std::move(s2);

}

int main(int argc, char *argv[])
{
    test2();
    return 0;
}

